﻿using Microsoft.SharePoint;

namespace Uportal.Shp.Core.Common
{
    using System;
    using System.Diagnostics;
    using System.Reflection;
    using Extension;
    using NLog;
    using NLog.Config;
    using NLog.Layouts;
    using NLog.Targets;
    public class NLogLogger
    {
        private static Logger _logger;

        public NLogLogger()
        {
            var config = new LoggingConfiguration();
            var target = new FileTarget();
            target.ArchiveAboveSize = 1024 * 100;
            target.MaxArchiveFiles = 30;
            target.FileName = new SimpleLayout("c:\\Temp\\Logs\\${shortdate}.log");
            var layout = new SimpleLayout("${date}|${level:uppercase=true}|${message} ${exception:format=tostring}");
            target.Layout = layout;
            config.AddTarget("file", target);

            var rule = new LoggingRule("*", LogLevel.Trace, target);
            config.LoggingRules.Add(rule);

            LogManager.Configuration = config;

            _logger = LogManager.GetCurrentClassLogger();
        }

        public NLogLogger(string logPath)
        {
            var config = new LoggingConfiguration();
            var target = new FileTarget();
            target.ArchiveAboveSize = 1024 * 100;
            target.MaxArchiveFiles = 30;
            target.FileName = new SimpleLayout(logPath);
            var layout = new SimpleLayout("${date}|${level:uppercase=true}|${message} ${exception:format=tostring}");
            target.Layout = layout;
            config.AddTarget("file", target);

            var rule = new LoggingRule("*", LogLevel.Trace, target);
            config.LoggingRules.Add(rule);

            LogManager.Configuration = config;

            _logger = LogManager.GetCurrentClassLogger();
        }

        public string LogFileName
        {
            get
            {
                return ((FileTarget)LogManager.Configuration.AllTargets[0]).FileName.ToString();
            }
            set
            {
                ((FileTarget)LogManager.Configuration.AllTargets[0]).FileName = value;
            }
        }

        public void Info(string message, params object[] args)
        {
            SPSecurity.RunWithElevatedPrivileges(() => _logger.Info(message, args));
        }

        public void Error(string message, params object[] args)
        {
            SPSecurity.RunWithElevatedPrivileges(() => _logger.Error(message, args));
        }

        public void Exception(Exception exception)
        {
            SPSecurity.RunWithElevatedPrivileges(() => _logger.ErrorException(exception.Message, exception));
        }

        public void Dump(object objectToDump)
        {
            Type t = objectToDump.GetType();

            var dump = new System.Text.StringBuilder();
            dump.AppendFormatLine("-----------DUMP OF {0}, HASH: {1} ------------", t.ToString(), objectToDump.GetHashCode());

            var props = t.GetProperties();
            var fields = t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
            dump.AppendLine("Properties:");
            foreach (var p in props)
            {
                var val = p.GetValue(objectToDump, null);

                string value = val == null
                    ? "null"
                    : val.ToString();

                dump.AppendFormatLine("\t{0} = {1}", p.Name, value);
            }

            dump.AppendLine();
            dump.AppendLine("Fields:");
            foreach (FieldInfo fieldInfo in fields)
            {
                if (fieldInfo.Name.Contains("BackingField")) continue;

                var val = fieldInfo.GetValue(objectToDump);

                string value = val == null
                    ? "null"
                    : val.ToString();

                string modifier = fieldInfo.IsPrivate
                    ? "private "
                    : fieldInfo.IsPublic
                        ? "public "
                        : fieldInfo.IsAssembly
                            ? "internal "
                            : fieldInfo.IsFamily
                                ? "protected"
                                : string.Empty;

                dump.AppendFormatLine("\t{0} {1} = {2}", modifier, fieldInfo.Name, value);
            }

            dump.Append("---------------------------------------------");
            Info(dump.ToString());
        }
    }
}
